﻿using Framework.Common.SystemOperation;
using Microsoft.AspNet.Identity;
using Microsoft.Owin.Security;
using PaPaPa.Data;
using PaPaPa.Web.Business.Accounts;
using PaPaPa.Web.Common.IO;
using PaPaPa.Web.Models.Accounts;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;

namespace PaPaPa.Areas.User.Controllers
{
    [Authorize]
    public class AccountController : Controller
    {
        //
        // GET: /Account/Login
        [AllowAnonymous]
        public ActionResult Login(string returnUrl)
        {
            ViewBag.ReturnUrl = returnUrl;
            return View();
        }

        //
        // POST: /Account/Login
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Login(string returnUrl, LoginViewModel model)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    var user = await AccountBusiness.FindAsync(model);

                    await SignInAsync(user, model.RememberMe);
                    if (!string.IsNullOrWhiteSpace(returnUrl))
                    {
                        return RedirectToLocal(returnUrl);
                    }
                    else
                    {
                        return RedirectToRoute(UrlConstant.HOME);
                    }
                }
                catch (Exception ex)
                {
                    ModelState.AddModelError("", ex.Message);
                }
            }

            // 如果我们进行到这一步时某个地方出错，则重新显示表单
            return View(model);
        }

        //
        // GET: /Account/Register
        [AllowAnonymous]
        public ActionResult Register()
        {
            return View();
        }

        //
        // POST: /Account/Register
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Register(string returnUrl, RegisterViewModel model)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    var user = await AccountBusiness.CreateAsync(model);
                    await SignInAsync(user, isPersistent: false);
                    if (!string.IsNullOrWhiteSpace(returnUrl))
                    {
                        return RedirectToLocal(returnUrl);
                    }
                    else
                    {
                        return RedirectToRoute(UrlConstant.HOME);
                    }
                }
                catch (Exception ex)
                {
                    ModelState.AddModelError("", ex.Message);
                }
            }

            // 如果我们进行到这一步时某个地方出错，则重新显示表单
            return View(model);
        }

        public ActionResult Manage(string message)
        {
            ViewBag.StatusMessage = message;
            ViewBag.ReturnUrl = Url.Action("Manage");
            return View();
        }

        //
        // POST: /Account/Manage
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Manage(ModifyPasswordViewModel model)
        {
            ViewBag.ReturnUrl = Url.Action("Manage");

            if (ModelState.IsValid)
            {
                try
                {
                    await AccountBusiness.ModifyPasswordAsync(Int32.Parse(User.Identity.GetUserId()), model.OldPassword, model.NewPassword);
                    return RedirectToAction("Manage", new { Message = "你的密码已更改。" });
                }
                catch (Exception ex)
                {
                    ModelState.AddModelError("", ex.Message);
                }
            }

            // 如果我们进行到这一步时某个地方出错，则重新显示表单
            return View(model);
        }

        //
        // POST: /Account/LogOff
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult LogOff(string returnUrl)
        {
            AuthenticationManager.SignOut();
            return Redirect(returnUrl);
        }

        //
        // Get: /Account/UserBasicData
        public async Task<ActionResult> ModifyUserBasicData(string message)
        {
            ViewBag.StatusMessage = message;
            ViewBag.ReturnUrl = Url.Action("ModifyUserBasicData");

            var model = await AccountBusiness.GetUserBasicDataByIdAsync(Int32.Parse(User.Identity.GetUserId()));

            return View(model); ;
        }

        //
        // Post: /Account/UserBasicData
        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> ModifyUserBasicData(UserBasicDataViewModel model)
        {
            ViewBag.ReturnUrl = Url.Action("ModifyUserBasicData");
            if (ModelState.IsValid)
            {
                try
                {
                    await AccountBusiness.ModifyUserBasicData(model);
                    return RedirectToAction("ModifyUserBasicData", new { Message = "你的基本资料已更改。" });
                }
                catch (Exception ex)
                {
                    ModelState.AddModelError("", ex.Message);
                }
            }
            return View(model);
        }


        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Upload()
        {
            // 初始化一大堆变量
            string inputName = "imgFile";//表单文件域name
            //string attachdir = System.Configuration.ConfigurationManager.AppSettings["UploadPath"];     // 上传文件保存路径

            string attachDir = SystemLib.GetAppRootDir("Upload");

            int maxAttachSize = 2097152;// 最大上传大小，默认是2M
            byte[] fileBytes;// 统一转换为byte数组处理
            string originalFileName = "";
            string disposition = Request.ServerVariables["HTTP_CONTENT_DISPOSITION"];
            string immediate = Request.QueryString["immediate"] ?? "0";

            string err = "";
            string msg = "''";

            if (disposition != null)
            {
                // HTML5上传
                fileBytes = Request.BinaryRead(Request.TotalBytes);
                originalFileName = Server.UrlDecode(Regex.Match(disposition, "filename=\"(.+?)\"").Groups[1].Value);// 读取原始文件名
            }
            else
            {
                HttpFileCollectionBase filecollection = Request.Files;
                HttpPostedFileBase postedfile = filecollection[inputName];

                // 读取原始文件名
                originalFileName = postedfile.FileName;
                // 初始化byte长度.
                fileBytes = new Byte[postedfile.ContentLength];

                // 转换为byte类型
                System.IO.Stream stream = postedfile.InputStream;
                stream.Read(fileBytes, 0, postedfile.ContentLength);
                stream.Close();

                filecollection = null;
            }

            if (fileBytes.Length == 0)
            {
                err = "无数据提交";
                return Json(new { msg = msg, err = err });
            }

            if (fileBytes.Length > maxAttachSize)
            {
                err = "文件大小超过" + maxAttachSize + "字节";
                return Json(new { msg = msg, err = err });
            }

            try
            {
                var saveRelativePath = FileOperation.SaveImage(fileBytes, originalFileName, attachDir);
                string target = System.Configuration.ConfigurationManager.AppSettings["UploadUrl"] + saveRelativePath.Replace("\\", "/").Replace("//", "/");
                //target = SystemLib.GetAppRootDir("UpLoad") + Path.Combine(attach_subdir, filename);
                // 立即模式判断
                if (immediate == "1") target = "!" + target;

                //msg = "{'url':'" + target + "','localname':'" + localname + "','id':'1'}";
                msg = target;
            }
            catch (Exception ex)
            {
                err = ex.Message;
                return Json(new { msg = msg, err = err });
            }

            fileBytes = null;

            //return new ContentResult() { Content = "{'err':'" + err + "','msg':" + msg + "}" };

            return Json(new { msg = msg, err = err });
        }

        #region 帮助程序
        // Used for XSRF protection when adding external logins
        private const string XsrfKey = "XsrfId";

        private IAuthenticationManager AuthenticationManager
        {
            get
            {
                return HttpContext.GetOwinContext().Authentication;
            }
        }

        private async Task SignInAsync(UserModel userModel, bool isPersistent)
        {
            AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
            ClaimsIdentityFactory<UserModel> claimsIdentityFactory = new ClaimsIdentityFactory<UserModel>();
            using (var userManager = new UserManager<UserModel>(userModel))
            {
                var identity = await claimsIdentityFactory.CreateAsync(userManager, userModel, DefaultAuthenticationTypes.ApplicationCookie);
                AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
            }
        }

        private ActionResult RedirectToLocal(string returnUrl)
        {
            if (Url.IsLocalUrl(returnUrl))
            {
                return Redirect(returnUrl);
            }
            else
            {
                //todo 跳转用户中心
                return RedirectToRoute(UrlConstant.HOME);
            }
        }

        private class ChallengeResult : HttpUnauthorizedResult
        {
            public ChallengeResult(string provider, string redirectUri)
                : this(provider, redirectUri, null)
            {
            }

            public ChallengeResult(string provider, string redirectUri, string userId)
            {
                LoginProvider = provider;
                RedirectUri = redirectUri;
                UserId = userId;
            }

            public string LoginProvider { get; set; }
            public string RedirectUri { get; set; }
            public string UserId { get; set; }

            public override void ExecuteResult(ControllerContext context)
            {
                var properties = new AuthenticationProperties() { RedirectUri = RedirectUri };
                if (UserId != null)
                {
                    properties.Dictionary[XsrfKey] = UserId;
                }
                context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
            }
        }
        #endregion
    }
}